﻿using SketchUpAPI.NET.Enums;
using SketchUpAPI.NET.SketchUp.Exception;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace SketchUpAPI.NET.Objects.Tables
{
    /// <summary>
    /// 场景表
    /// </summary>
    /// <remarks>
    /// 注意：该类型并非 SketchUpAPI 接口中存在的类型，而是该 API 为方便管理组件定义而创建的类型。该类型的 Id 使用的是 <see cref="SketchUp.SketchUpModel"/> 的 Id
    /// </remarks>
    public class SceneTable : ObjectBase
    {
        #region API 函数
        /// <summary>
        /// 获取场景个数
        /// </summary>
        /// <param name="model"></param>
        /// <param name="num_scenes"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUModelGetNumScenes(IntPtr model, out int num_scenes);

        /// <summary>
        /// 获取全部场景
        /// </summary>
        /// <param name="model"></param>
        /// <param name="len"></param>
        /// <param name="scenes"><see cref="Scene"/></param>
        /// <param name="realcount"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUModelGetScenes(IntPtr model, int len, IntPtr[] scenes, out int realcount);

        /// <summary>
        /// 获取对应名字的场景
        /// </summary>
        /// <param name="model"></param>
        /// <param name="name"></param>
        /// <param name="scene"><see cref="Scene"/></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUModelGetSceneWithName(IntPtr model, [MarshalAs(UnmanagedType.LPUTF8Str)] string name, out IntPtr scene);

        /// <summary>
        /// 添加多个场景
        /// </summary>
        /// <param name="model"></param>
        /// <param name="len"></param>
        /// <param name="scenes"><see cref="Scene"/></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUModelAddScenes(IntPtr model, int len, IntPtr[] scenes);

        /// <summary>
        /// 添加一个场景
        /// </summary>
        /// <param name="model"></param>
        /// <param name="index">要将场景添加到第一个位置，-1表示在最后</param>
        /// <param name="scene"><see cref="Scene"/></param>
        /// <param name="out_index">该场景的索引</param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUModelAddScene(IntPtr model, int index, IntPtr scene, out int out_index);

        /// <summary>
        /// 获取当前场景
        /// </summary>
        /// <param name="model"></param>
        /// <param name="scene"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUModelGetActiveScene(IntPtr model, out IntPtr scene);

        /// <summary>
        /// 设置激活的场景
        /// </summary>
        /// <param name="model"></param>
        /// <param name="scene"></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUModelSetActiveScene(IntPtr model, IntPtr scene);

        /// <summary>
        /// 添加照片匹配场景
        /// </summary>
        /// <param name="model"></param>
        /// <param name="image_file">图片路径</param>
        /// <param name="camera"><see cref="Camera"/>相机</param>
        /// <param name="scene_name">场景名字</param>
        /// <param name="scene"><see cref="Scene"/></param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUModelAddMatchPhotoScene(IntPtr model, [MarshalAs(UnmanagedType.LPUTF8Str)] string image_file, IntPtr camera, [MarshalAs(UnmanagedType.LPUTF8Str)] string scene_name, out IntPtr scene);

        /// <summary>
        /// 删除场景
        /// </summary>
        /// <param name="model"></param>
        /// <param name="len"></param>
        /// <param name="scenes"><see cref="Objects.Scene"/>[]</param>
        /// <returns></returns>
        [DllImport(LIB)]
        static extern SUResult SUModelRemoveScenes(IntPtr model, int len, IntPtr[] scenes);
        #endregion

        /// <summary>
        /// 场景个数
        /// </summary>
        public int Count
        {
            get
            {
                SketchUpExceptionHelper.ThrowSUResult(SUModelGetNumScenes(Id, out int n));
                return n;
            }
        }

        /// <summary>
        /// 全部场景
        /// </summary>
        public List<Scene> Scenes
        {
            get
            {
                IntPtr[] pts = new IntPtr[Count];
                SketchUpExceptionHelper.ThrowSUResult(SUModelGetScenes(Id, pts.Length, pts, out _));
                return pts.Select(i => new Scene(i)).ToList();
            }
        }

        /// <summary>
        /// 当前场景
        /// </summary>
        public Scene ActiveScene
        {
            get
            {
                SketchUpExceptionHelper.ThrowSUResult(SUModelGetActiveScene(Id, out IntPtr id));
                return new Scene(id);
            }
            set
            {
                SketchUpExceptionHelper.ThrowSUResult(SUModelSetActiveScene(Id, value.Id));
            }
        }

        /// <summary>
        /// 使用场景名称获取场景
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public Scene this[string name]
        {
            get
            {
                SketchUpExceptionHelper.ThrowSUResult(SUModelGetSceneWithName(Id, name, out IntPtr id));
                return new Scene(id);
            }
        }

        internal SceneTable(IntPtr id) => Id = id;

        /// <summary>
        /// 添加场景
        /// </summary>
        /// <param name="scenes"></param>
        public void Add(params Scene[] scenes)
        {
            SketchUpExceptionHelper.ThrowSUResult(SUModelAddScenes(Id, scenes.Length, scenes.Select(s => s.Id).ToArray()));
        }

        /// <summary>
        /// 添加场景
        /// </summary>
        /// <param name="scene"></param>
        /// <param name="index">要将场景添加到第一个位置，-1表示在最后</param>
        /// <returns></returns>
        public int Add(Scene scene, int index = -1)
        {
            SketchUpExceptionHelper.ThrowSUResult(SUModelAddScene(Id, index, scene.Id, out int realIndex));
            return realIndex;
        }

        /// <summary>
        /// 添加照片匹配
        /// </summary>
        /// <param name="imageFile"></param>
        /// <param name="camera"></param>
        /// <param name="sceneName"></param>
        /// <returns></returns>
        public Scene AddPhotoMatch(string imageFile, Camera camera, string sceneName)
        {
            SketchUpExceptionHelper.ThrowSUResult(SUModelAddMatchPhotoScene(Id, imageFile, camera.Id, sceneName, out IntPtr id));
            return new Scene(id);
        }

        /// <summary>
        /// 删除场景
        /// </summary>
        /// <param name="scenes"></param>
        public void Remove(params Scene[] scenes)
        {
            SketchUpExceptionHelper.ThrowSUResult(SUModelRemoveScenes(Id, scenes.Length, scenes.Select(s => s.Id).ToArray()));
        }
    }
}